#include <iostream>
#include <fstream>
#include "contacts.pb.h"

void PrintContacts(contacts2::Contacts contacts)
{
    for(int i = 0;i < contacts.contacts_size();i++)  // contacts存储的是一个数组，数组大小使用内置函数，依次遍历
    {
        std::cout << "--------------" << "联系人" << i+1 << "--------------" << std::endl;
        const contacts2::PeopleInfo& people = contacts.contacts(i);  // 使用这个下标
        // 1.打印姓名年龄
        std::cout << "联系人的姓名：" << people.name() << std::endl;
        std::cout << "联系人的年龄：" << people.age() << std::endl;

        // 2.打印电话号码：同样，也是一个数组
        // 遍历电话号码数组
        for(int j = 0;j < people.phone_size();j++)
        {
            const contacts2::PeopleInfo_Phone& phone = people.phone(j);  // 使用这个下标的电话号码
            std::cout << "联系人电话" << j+1 << phone.number();
            // phone.type() 是原始的数字，比如MP是0，TLE是1，而我们想要的是它对应的名字，所以套一层name接口
            std::cout << "   (" << phone.PhoneType_Name(phone.type()) << ")" << std::endl;
        }

        // 3.打印地址信息
        // 打印之前，先检查是否在data里面
        if(people.has_data() && people.data().Is<contacts2::Address>())  // 第一个是判断Any对象data中是否存储有效信息，第二个是判断如果设置了有效信息并且设置的是Address类型，才可以进行打印操作
        {
            contacts2::Address address;
            // people.data() 拿到的是Any类型的data
            people.data().UnpackTo(&address);  // 将Any类型的data转换成Address类型，存入到address中，此时address拿到的就是这个联系人的地址
            if(!address.home_address().empty())  // 如果设置了才打印
                std::cout << "家庭住址为：" << address.home_address() << std::endl;
            if(!address.unit_address().empty())  // 如果设置了才打印
                std::cout << "单位住址为：" << address.unit_address() << std::endl;
        }

        // 4.打印其他联系方式
        switch (people.other_contact_case())
        {
            case contacts2::PeopleInfo::OtherContactCase::kQq:
                std::cout << "联系人的qq号为：" << people.qq() << std::endl;
                break;
            case contacts2::PeopleInfo::OtherContactCase::kWechat:
                std::cout << "联系人的wechat号为：" << people.wechat() << std::endl;
                break;
            default:
                break;
        }

        // 5.打印备注信息
        if(people.remark_size())
            std::cout << "备注信息：" << std::endl;
        // 打印方式和c++差不多
        for(auto it = people.remark().begin();it != people.remark().end();it++)
            std::cout << "    " << it->first << ": " << it->second << std::endl;
    }
}

int main()
{
    contacts2::Contacts contacts;
    // 1.读取本地已经存在的通讯录文件
    std::fstream input("contacts.bin", std::ios::in | std::ios::binary); // 由于序列化之后是二进制的文件，所以以.bin结尾，并且以二进制的方式读取
    if(!contacts.ParseFromIstream(&input))  // 反序列化，从istream中获取
    {
        std::cerr << "反序列化失败！" << std::endl;
        input.close();  // 关闭文件流
        return -1;
    }

    // 2. 打印通讯录列表
    PrintContacts(contacts);
    return 0;
}